package cn.wolfcode.wolf2w.business.service.impl;

import cn.wolfcode.wolf2w.business.api.RemoteDestinationService;
import cn.wolfcode.wolf2w.business.api.RemoteNoteCommentService;
import cn.wolfcode.wolf2w.business.api.RemoteNoteService;
import cn.wolfcode.wolf2w.business.api.RemoteStrategyService;
import cn.wolfcode.wolf2w.business.api.domain.Destination;
import cn.wolfcode.wolf2w.business.api.domain.Note;
import cn.wolfcode.wolf2w.business.api.domain.Strategy;
import cn.wolfcode.wolf2w.business.query.SearchQuery;
import cn.wolfcode.wolf2w.business.service.ISearchService;
import cn.wolfcode.wolf2w.common.core.constant.SecurityConstants;
import cn.wolfcode.wolf2w.member.api.RemoteUserInfoService;
import cn.wolfcode.wolf2w.member.api.domain.UserInfo;
import org.apache.commons.beanutils.BeanUtils;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Service
public class SearchServiceImpl implements ISearchService {
    @Autowired
    private ElasticsearchRestTemplate template;
    @Autowired
    private RemoteStrategyService remoteStrategyService;
    @Autowired
    private RemoteNoteService remoteNoteService;
    @Autowired
    private RemoteUserInfoService remoteUserInfoService;
    @Autowired
    private RemoteDestinationService remoteDestinationService;

    @Override
    public <T> Page<T> searchWithHighLight(Class<T> clazz, Class<?> esClazz, SearchQuery qo, String... fields) throws InvocationTargetException, IllegalAccessException {

        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.withQuery(
                QueryBuilders.multiMatchQuery(qo.getKeyword(), fields)
        );
        //elasticSearch 中分页从0开始，需要减一
        PageRequest pageable = PageRequest.of(qo.getCurrentPage() - 1, qo.getPageSize());
        builder.withPageable(pageable);

        List<HighlightBuilder.Field> fieldList = new ArrayList<>();
        for (String name : fields) {
            HighlightBuilder.Field field = new HighlightBuilder.Field(name)
                    .preTags("<span style='color:red'>")
                    .postTags("</span>");
            fieldList.add(field);
        }
        builder.withHighlightFields(fieldList);

        SearchHits<?> hits = template.search(builder.build(), esClazz);
        long total = hits.getTotalHits();

        List<T> tList = new ArrayList<>();
        for (SearchHit<?> hit : hits) {
            Long id = Long.valueOf(hit.getId());
            T t = null;  //mysql中的原数据
            if (clazz== Strategy.class){
                t = (T) remoteStrategyService.getOne(id, SecurityConstants.INNER).getData();
            }else if (clazz== Note.class){
                t = (T) remoteNoteService.getOne(id, SecurityConstants.INNER).getData();
            }else if (clazz== UserInfo.class){
                t = (T) remoteUserInfoService.getOne(id, SecurityConstants.INNER).getData();
            }else if (clazz== Destination.class){
                t = (T) remoteDestinationService.getOne(id, SecurityConstants.INNER).getData();
            }
            Map<String, List<String>> highlightFields = hit.getHighlightFields();
            Set<String> keySet = highlightFields.keySet();
            for (String key : keySet) {
                List<String> list = highlightFields.get(key);
                StringBuffer sb = new StringBuffer();
                for (String s : list) {
                    sb.append(s).append("&nbsp;&nbsp;");
                }
                String value = sb.toString();
                BeanUtils.setProperty(t,key,value);
            }
            tList.add(t);
        }
        //构建分页数据并返回
        return new PageImpl<T>(tList,pageable,total);
    }
}
